package snmp_trap;

import java.io.IOException;
import java.util.Vector;

import org.snmp4j.CommandResponder;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.MessageDispatcherImpl;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.mp.MPv1;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.mp.MPv3;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.TcpAddress;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultTcpTransportMapping;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.MultiThreadedMessageDispatcher;
import org.snmp4j.util.ThreadPool;

/**
 * 本类用于监听代理进程的Trap信息
 */
public class MultiThreadedTrapReceiver implements CommandResponder {

	private MultiThreadedMessageDispatcher dispatcher;
	private Snmp snmp;
	private Address listenAddress;
	private ThreadPool threadPool;

	public MultiThreadedTrapReceiver() {
		super();
	}

	private void init() throws IOException {
		threadPool = ThreadPool.create("Trap", 2);
		dispatcher = new MultiThreadedMessageDispatcher(threadPool,	new MessageDispatcherImpl());
		listenAddress = GenericAddress.parse(System.getProperty("snmp4j.listenAddress", "udp:127.0.0.1/162"));// 本地监听IP与端口
		
		TransportMapping transport;
		// 对TCP和UDP协议进行处理
		if (listenAddress instanceof UdpAddress) {
			transport = new DefaultUdpTransportMapping((UdpAddress) listenAddress);
		} else {
			transport = new DefaultTcpTransportMapping((TcpAddress) listenAddress);
		}
		snmp = new Snmp(dispatcher, transport);
		snmp.getMessageDispatcher().addMessageProcessingModel(new MPv1());
		snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());
		snmp.getMessageDispatcher().addMessageProcessingModel(new MPv3());
		USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
		SecurityModels.getInstance().addSecurityModel(usm);
		// 开始启动trap监听.listen()方法内部启动了一个线程,
		// 这个线程监听发送到transport中定义的端口的消息.
		snmp.listen();
	}
	
	public void run() {
		try {
			init();
			snmp.addCommandResponder(this);// 给snmp增加监听器
			System.out.println("开始监听Trap信息！");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 实现CommandResponder的processPdu方法，用于处理传入的请求，PDU信息
	 * 当接收到Trap时，会自动进入这个方法
	 */
	public void processPdu(CommandResponderEvent respEvent) {
		if (respEvent != null && respEvent.getPDU() != null) {
			Vector vecVBs = respEvent.getPDU().getVariableBindings();
			for (int i = 0; i < vecVBs.size(); i++) {
				VariableBinding vecVB = (VariableBinding) vecVBs.get(i);
				System.out.println(vecVB.getOid() + ":" + vecVB.getVariable());
			}
		}
	}

	public static void main(String[] args) {
		MultiThreadedTrapReceiver mutMultiThreadedTrapReceiver = new MultiThreadedTrapReceiver();
		mutMultiThreadedTrapReceiver.run();
	}
}
